package com.zbs.framework.security.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.zbs.framework.common.constant.Constants;
import com.zbs.framework.common.redis.RedisUtil;
import com.zbs.framework.common.utils.BeanUtils;
import com.zbs.framework.common.utils.CommonUtil;
import com.zbs.framework.security.config.FrameworkConstants;
import com.zbs.framework.security.entity.LoginUser;
import com.zbs.framework.security.entity.LoginUserInfo;
import com.zbs.framework.security.entity.SecurityUser;
import com.zbs.framework.security.service.SuccessfulAuthenticationService;
import com.zbs.framework.security.service.TokenLoginService;
import com.zbs.framework.security.utils.PasswordEncoderUtil;
import com.zbs.framework.security.utils.TokenManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 此类可重写
 * PasswordEncoder 一定要注入进来
 * <p>
 */
@Transactional
@Service
@Slf4j
public class TokenLoginServiceImpl implements TokenLoginService {


    @Override
    public Map<String, Object> successfulAuthentication(String token, SecurityUser user) {
        //参数构建
        final LoginUserInfo loginUserInfo = LoginUserInfo.build()
                .setId(user.getLoginUser().getId())
                .setUsername(user.getUsername())
                .setToken(token)
                .setUserType(user.getLoginUser().getUserType())
                .setEnabled(user.isEnabled())
                .setPermissions(user.getPermissions());

        // 把实体转换map
        Map<String, Object> objectMap = CommonUtil.beanToMap(loginUserInfo);
        // 当基础信息不足时，作用域存储其他信息
        Map<String, Object> otherInfo = new HashMap<>();
        // 
        objectMap.put("userInfo", user.getUserInfo());
        final String entryType = user.getLoginUser().getEntryType();

        SuccessfulAuthenticationService successfulAuthenticationService = null;
        try {
            successfulAuthenticationService = BeanUtils.getBean(SuccessfulAuthenticationService.class);
        } catch (BeansException e) {
            log.info("SuccessfulAuthenticationService 没有被初始化，如果需要使用，请实现 SuccessfulAuthenticationService");
        }
        if (successfulAuthenticationService != null) {
            successfulAuthenticationService.successfulAuthentication(objectMap,otherInfo, user, entryType, token);
        }
        loginUserInfo.setOtherInfo(otherInfo);
        //判断是否多端配置
        if (FrameworkConstants.IS_SSO && FrameworkConstants.IS_MULTI_TERMINAL) {
            //存入redis
            RedisUtil.set(Constants.tokenPrefix + CommonUtil.MD5_32(user.getLoginUser().getUsername()) + Constants.tokenSuffix + entryType, JSONObject.toJSONString(loginUserInfo), FrameworkConstants.TOKEN_EXPIRATION);
        } else {
            RedisUtil.set(Constants.tokenPrefix + CommonUtil.MD5_32(user.getLoginUser().getUsername()) + Constants.tokenSuffix + "1", JSONObject.toJSONString(loginUserInfo), FrameworkConstants.TOKEN_EXPIRATION);
        }
        return objectMap;
    }

    @Override
    public Map<String, Object> login(Long id, String username,String pwd, String presentedPassword, String entryType,  Character userType, List<String> permissions, Object userInfo, Map<String, Object> otherParameters, boolean isEnabled) {
        if (entryType == null) {
            entryType = "1";
        }
        //登录用户信息 手机号不需要密码
        LoginUser curUser = LoginUser.build()
                .setId(id)
                .setEntryType(entryType)
                .setPassword(pwd,StringUtils.hasLength(pwd))
                .setUserType(userType)
                .setUsername(username);

        // 组装成  SecurityUser
        SecurityUser securityUser = new SecurityUser(curUser, permissions, userInfo, otherParameters, isEnabled);
        // 密码校验
        if (StringUtils.hasLength(pwd) && StringUtils.hasLength(presentedPassword)) {
            PasswordEncoderUtil.checkUserPassword(securityUser, presentedPassword);
        }
        // 创建token
        final String token = TokenManager.createToken(id.toString(),username,entryType);
        // 去登录
        return this.successfulAuthentication(token,securityUser);
    }

    @Override
    public Map<String, Object> login(Long id, String username, String pwd, String presentedPassword, List<String> permissions, Object userInfo, Map<String, Object> otherParameters, boolean isEnabled) {
        return this.login(id, username, pwd,presentedPassword,"1", '1', permissions, userInfo, otherParameters, isEnabled);
    }

    @Override
    public Map<String, Object> login(Long id, String username, List<String> permissions, Object userInfo, Map<String, Object> otherParameters, boolean isEnabled) {
        return this.login(id, username, null,null,"1", '1', permissions, userInfo, otherParameters, isEnabled);
    }

    @Override
    public Map<String, Object> login(Long id, String username, String entryType, Character userType, List<String> permissions, Object userInfo, Map<String, Object> otherParameters, boolean isEnabled) {
        return this.login(id, username, null,null,entryType,userType, permissions, userInfo, otherParameters, isEnabled);
    }
}
